---
title: Relations
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

When using the `nestjs-query` you can specify relations that should be exposed for the DTO using the following decorators.

* `@Relation` - A relation that is a single value (one-to-one, many-to-one)
* `@FilterableRelation` - A `@Relation` that enables filtering the parent by fields of the relation `DTO`.
* `@UnPagedRelation` - An array of relations (e.g, many-to-many, one-to-many) that returns all of the related records.
* `@FilterableUnPagedRelation` - An `@UnPagedRelation` that enables filtering the parent by fields of the relation
`DTO`.
* `@OffsetConnection` - A connection that represents a collection (e.g, many-to-many, one-to-many) that uses `offset`
 based pagination.
* `@FilterableOffsetConnection` - An `@OffsetConnection` that enables filtering the parent by fields of the connection
 `DTO`.
* `@CursorConnection` - A connection that represents a collection (e.g, many-to-many, one-to-many) that uses `cursor`
 based pagination.
* `@FilterableCursorConnection` - A `@CursorConnection` that enables filtering the parent by fields of the
 connection `DTO`.

:::warning
`@FilterableUnPagedRelation`, `@FilterableOffsetConnection`, and `@FilterableCursorConnection` are not supported by
mongoose!
:::

:::note
When loading relations a [dataloader](https://github.com/graphql/dataloader) that is scoped to the request will be used. This prevents the n+1 problem.
:::

In the following examples we are going to use the following entities.

<Tabs
  defaultValue="todoitementity"
  values={[
    { label: 'TodoItemEntity', value: 'todoitementity', },
    { label: 'SubTaskEntity', value: 'subtaskentity', },
  ]
}>
<TabItem value="todoitementity">

```ts title="todo-item/todo-item.entity.ts"
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, OneToMany } from 'typeorm';
import { SubTaskEntity } from '../sub-task/sub-task.entity';

@Entity()
export class TodoItemEntity {
  @PrimaryGeneratedColumn()
  id!: string;

  @Column()
  title!: string;

  @Column()
  completed!: boolean;

  @OneToMany(
    () => SubTaskEntity,
    subTask => subTask.todoItem,
  )
  subTasks!: SubTaskEntity[];

  @CreateDateColumn()
  created!: Date;

  @UpdateDateColumn()
  updated!: Date;
}

```

</TabItem>
<TabItem value="subtaskentity">

```ts title="sub-task/sub-task.entity.ts"
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  ObjectType,
  ManyToOne,
  JoinColumn,
} from 'typeorm';
import { TodoItemEntity } from '../todo-item/todo-item.entity';

@Entity()
export class SubTaskEntity {
  @PrimaryGeneratedColumn()
  id!: string;

  @Column()
  title!: string;

  @Column()
  completed!: boolean;

  @Column({ nullable: false })
  todoItemId!: string;

  @ManyToOne(
    (): ObjectType<TodoItemEntity> => TodoItemEntity,
    td => td.subTasks,
    { onDelete: 'CASCADE', nullable: false },
  )
  @JoinColumn()
  todoItem!: TodoItemEntity;

  @CreateDateColumn()
  created!: Date;

  @UpdateDateColumn()
  updated!: Date;
}

```
</TabItem>
</Tabs>

## @Relation

A relation that is a single value (one-to-one, many-to-one)

### Example

Based on the entities defined above we can add a `todoItem` relation to the `SubTask` by creating the following `SubTaskDTO` with a `@Relation` decorator.


```ts title="sub-task/sub-task.dto.ts" {6}
import { FilterableField, IDField, Relation } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { TodoItemDTO } from '../todo-item/todo-item.dto.ts';

@ObjectType('SubTask')
@Relation('todoItem', () => TodoItemDTO, { disableRemove: true })
export class SubTaskDTO {
  @FilterableField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;

  @FilterableField()
  todoItemId!: string;
}
```

The `@Relation` decorator lets `nestjs-query` know to expose the following endpoints:

* `subTask.todoItem` - A `query` to retrieve the `SubTasks` `TodoItem`
* `setTodoItemOnSubTask` - A `mutation` to set the `TodoItem` on a `SubTask`.
* `removeTodoItemFromSubTask` - A `mutation` to remove a `TodoItem`/`SubTask` relation.
    * **NOTE** This does not typically remove either record just removes the relation.

:::note
In this example we `disableRemove`, because `todoItem` is not nullable, by specifying the `disableRemove` option.
:::

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts title="sub-task/sub-task.module.ts"
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { SubTaskDTO } from './sub-task.dto';
import { SubTaskEntity } from './sub-task.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([SubTaskEntity])],
      resolvers: [{ DTOClass: SubTaskDTO, EntityClass: SubTaskEntity }],
    }),
  ],
})
export class SubTaskModule {}
```

`@nestjs-query/query-graphql` will then automatically create the following graphql definition:

```graphql
type SubTask {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  todoItemId: String!
  todoItem: TodoItem!
}
```

The following mutations will also be automatically exposed.

```graphql
type Mutation {
  setTodoItemOnSubTask(input: RelationInput!): SubTask!
}

input RelationInput {
  id: ID!
  relationId: ID!
}
```

:::note
If `disableRemove` was set to `false` or not specified a `removeTodoItemFromSubTask` mutation would also be exposed with the same arguments as `setTodoItemOnSubTask`.
:::

## @FilterableRelation

The `@FilterableRelation` extends the `@Relation` decorator exposing the ability to filter the `DTO` that defines the relation by relation properties.

:::warning
The `@FilterableRelation` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`,
`sequelize`). If your relations are federated or you are using `mongoose` you cannot use the `@FilterableRelation`
decorator.
:::

### Example

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `SubTasks` by `TodoItems`.

```ts title="sub-task/sub-task.dto.ts" {6}
import { FilterableField, IDField, FilterableRelation } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { TodoItemDTO } from '../todo-item/todo-item.dto.ts';

@ObjectType('SubTask')
@FilterableRelation('todoItem', () => TodoItemDTO, { disableRemove: true })
export class SubTaskDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;

  @FilterableField(() => ID)
  todoItemId!: string;
}
```
Notice the use of `@FilterableRelation` instead of `@Relation`, by using the `@FilterableRelation` version `nestjs-query` will allow filtering on the `todoItem` relation.

The  module definition remains the same.

```ts title="sub-task/sub-task.module.ts"
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { SubTaskDTO } from './sub-task.dto';
import { SubTaskEntity } from './sub-task.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([SubTaskEntity])],
      resolvers: [{ DTOClass: SubTaskDTO, EntityClass: SubTaskEntity }],
    }),
  ],
})
export class SubTaskModule {}
```

When querying for `SubTasks` you can now also filter on `todoItem` properties.

In this example we'll find all subTasks that are related to a `todoItem` with a title that starts with `Created`.
```graphql
{
  subTasks(filter: { todoItem: { title: { like: "Create%" } } }) {
    title
    completed
  }
}

```

## @UnPagedRelation

You can also use the `@UnPagedRelation` decorator to define a relation that does not use paging and returns an array
 of all the related records.

### Example

Based on the entity definition above we can define a `TodoItemDTO` with a `subTasks` relation.

```ts title="todo-item/todo-item.dto.ts" {6}
import { FilterableField, IDField, UnPagedRelation } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@UnPagedRelation('subTasks', () => SubTaskDTO, { disableRemove: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}

```

When specifying a many relation a couple of endpoints will automatically be generated. In this example the following are generated.

* `todoItem.subTasks` - A `query` endpoint to retrieve a `TodoItems` `SubTasks`.
    * The `subTasks` property will accept a [query](../concepts/queries.mdx) to allow you to filter, and sort results.
    * The `subTasks` will be returned as an array of results.
* `addSubTasksToTodoItem` - A `mutation` to add `SubTasks` to a `TodoItem`.

:::note
In this example we `disableRemove` because `SubTasks` cannot exist without a `TodoItem`.
:::

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts title="todo-item/todo-item.module.ts"
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { TodoItemDTO } from './todo-item.dto';
import { TodoItemEntity } from './todo-item.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }],
    }),
  ],
})
export class TodoItemModule {}
```

The generated schema will contain a `TodoItem` type like the following.

```graphql
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    filter: SubTaskFilter = {}
    sorting: [SubTaskSort!] = []
  ): [SubTask!]!
}
```

The following mutations will also be automatically exposed.

```graphql
type Mutation {
   addSubTasksToTodoItem(input: RelationsInput!): TodoItem!
}

input RelationsInput {
  id: ID!
  relationIds: [ID!]!
}
```

:::note
If `disableRemove` was set to `false` or not specified a `removeSubTasksFromTodoItem` mutation would also be exposed with the same arguments as `addSubTasksToTodoItem`.
:::

## @FilterableUnPagedRelation

The `@FilterableUnPagedRelation` extends the `@UnPagedRelation` decorator exposing the ability to filter the `DTO` that
defines the relation by relation properties.

:::warning
The `@FilterableUnPagedRelation` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`,
`sequelize`). If your relations are federated or you are using `mongoose` you cannot use the `@FilterableUnPagedRelation`
decorator.
:::

### Example

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `TodoItems`
 by `SubTasks`.

```ts title="sub-task/sub-task.dto.ts" {6}
import { FilterableField, IDField, FilterableUnPagedRelation } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@FilterableUnPagedRelation('subTasks', () => SubTaskDTO, { disableRemove: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}
```
Notice the use of `@FilterableUnPagedRelation` instead of `@UnPagedRelation`, by using the
`@FilterableUnPagedRelation` version `nestjs-query` will allow filtering on the `subTasks` relation.

The  module definition remains the same.

```ts title="sub-task/sub-task.module.ts"
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { TodoItemDTO } from './todo-item.dto';
import { TodoItemEntity } from './todo-item.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }],
    }),
  ],
})
export class TodoItemModule {}
```

When querying for `TodoItems` you can now also filter on `subTasks` properties.

In this example we'll find all `todoItems` that are related to a `subTasks` that are completed.
```graphql
{
  todoItems(filter: { subTasks: { completed: { is: true } } }) {
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    edges {
      node {
        id
        title
        description
        completed
        subTasks {
          title
          description
          completed
        }
      }
      cursor
    }
  }
}
```

## @OffsetConnection

### Example

Based on the entity definitions above we can create a `TodoItemDTO` with a connection to the `subTasks`.

```ts title="todo-item/todo-item.dto.ts" {6}
import { FilterableField, IDField, OffsetConnection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@OffsetConnection('subTasks', () => SubTaskDTO, { disableRemove: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}

```

When specifying a `@OffsetConnection` relation a couple of endpoints will automatically be generated. In this example
 the following are generated.

* `todoItem.subTasks` - A `query` to retrieve a `TodoItems` `SubTasks`.
    * The `subTasks` property will accept a [query](../concepts/queries.mdx) to allow you to filter, page and sort results.
    * The `subTasks` property will return a offset based [connection](./types.mdx#connectiontype) to page through
    results.
* `addSubTasksToTodoItem` - A `mutation` to add `SubTasks` to a `TodoItem`.

:::note
In this example we `disableRemove` because `SubTasks` cannot exist without a `TodoItem`.
:::

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts title="todo-item/todo-item.module.ts"
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { TodoItemDTO } from './todo-item.dto';
import { TodoItemEntity } from './todo-item.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }],
    }),
  ],
})
export class TodoItemModule {}
```

The generated schema will contain a `TodoItem` type like the following.

```graphql
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: OffsetPaging = { limit: 10 }

    filter: SubTaskFilter = {}

    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}
```

The following mutations will also be automatically exposed.

```graphql
type Mutation {
   addSubTasksToTodoItem(input: RelationsInput!): TodoItem!
}

input RelationsInput {
  id: ID!
  relationIds: [ID!]!
}
```

:::note
If `disableRemove` was set to `false` or not specified a `removeSubTasksFromTodoItem` mutation would also be exposed with the same arguments as `addSubTasksToTodoItem`.
:::

### Total Count Example

:::warning
Enabling `totalCount` can be expensive. If your table is large the `totalCount` query may be expensive, use with caution.
:::
:::info
The `totalCount` field is not eagerly fetched. It will only be executed if the field is queried from the client.
:::

When using the `@OffsetConnection` decorator you can enable the `totalCount` field. The `totalCount` field will return the total number of records included in the connection.

```ts title="todo-item/todo-item.dto.ts" {6}
import { FilterableField, IDField, OffsetConnection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@OffsetConnection('subTasks', () => SubTaskDTO, { disableRemove: true, enableTotalCount: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}

```

The generated graphql will include a `TodoItemSubTasksConnection` with a `totalCount` field.

```graphql {19}
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: OffsetPaging = { limit: 10 }

    filter: SubTaskFilter = {}

    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}

type TodoItemSubTasksConnection {
  pageInfo: OffsetPageInfo!
  nodes: [SubTask!]!
  totalCount: Int!
}

```


## @FilterableOffsetConnection

The `@FilterableOffsetConnection` extends the `@OffsetConnection` decorator exposing the ability to filter the `DTO`
that defines the relation by relation properties.

:::warning
The `@FilterableOffsetConnection` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`,
`sequelize`). If your relations are federated or you are using `mongoose` you cannot use the `@FilterableConnection`
decorator.
:::

### Example

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `TodoItems` by `subTasks`.

```ts title="todo-item/todo-item.dto.ts" {7}
import { FilterableField, IDField, FilterableOffsetConnection, QueryOptions } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@QueryOptions({ pagingStrategy: PagingStrategies.OFFSET })
@FilterableOffsetConnection('subTasks', () => SubTaskDTO, { disableRemove: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}

```
Notice the use of `@FilterableOffsetConnection` instead of `@OffsetConnection`, by using the
`@FilterableOffsetConnection` version `nestjs-query` will allow filtering on the `subTasks` relation.

The  module definition remains the same.

```ts title="todo-item/todo-item.module.ts"
import { PagingStrategies } from '@nestjs-query/core';
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { TodoItemDTO } from './todo-item.dto';
import { TodoItemEntity } from './todo-item.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }],
    }),
  ],
})
export class TodoItemModule {}
```

When querying for `TodoItems` you can now also filter on `subTasks` properties.

In this example we'll find all `todoItems` that have `subTasks` that are completed.
```graphql
{
  todoItems(filter: { subTasks: { completed: { is: true } } }) {
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
    nodes {
      id
      title
      description
      completed
      subTasks {
        nodes {
          title
          description
          completed
        }
      }
    }
  }
}
```

## @CursorConnection

### Example

Based on the entity definitions above we can create a `TodoItemDTO` with a connection to the `subTasks`.

```ts title="todo-item/todo-item.dto.ts" {6}
import { FilterableField, IDField, CursorConnection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@CursorConnection('subTasks', () => SubTaskDTO, { disableRemove: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}

```

When specifying a `@CursorConnection` relation a couple of endpoints will automatically be generated. In this example
 the
following are generated.

* `todoItem.subTasks` - A `query` to retrieve a `TodoItems` `SubTasks`.
    * The `subTasks` property will accept a [query](../concepts/queries.mdx) to allow you to filter, page and sort results.
    * The `subTasks` property will return a cursor based [connection](./types.mdx#connectiontype) to page through
    results.
* `addSubTasksToTodoItem` - A `mutation` to add `SubTasks` to a `TodoItem`.

:::note
In this example we `disableRemove` because `SubTasks` cannot exist without a `TodoItem`.
:::

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts title="todo-item/todo-item.module.ts"
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { TodoItemDTO } from './todo-item.dto';
import { TodoItemEntity } from './todo-item.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }],
    }),
  ],
})
export class TodoItemModule {}
```

The generated schema will contain a `TodoItem` type like the following.

```graphql
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: CursorPaging = { first: 10 }

    filter: SubTaskFilter = {}

    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}
```

The following mutations will also be automatically exposed.

```graphql
type Mutation {
   addSubTasksToTodoItem(input: RelationsInput!): TodoItem!
}

input RelationsInput {
  id: ID!
  relationIds: [ID!]!
}
```

:::note
If `disableRemove` was set to `false` or not specified a `removeSubTasksFromTodoItem` mutation would also be exposed with the same arguments as `addSubTasksToTodoItem`.
:::

### Total Count Example

:::warning
Enabling `totalCount` can be expensive. If your table is large the `totalCount` query may be expensive, use with caution.
:::
:::info
The `totalCount` field is not eagerly fetched. It will only be executed if the field is queried from the client.
:::

When using the `@CursorConnection` decorator you can enable the `totalCount` field. The `totalCount` field will return the total number of records included in the connection.

```ts title="todo-item/todo-item.dto.ts" {6}
import { FilterableField, IDField, Connection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@CursorConnection('subTasks', () => SubTaskDTO, { disableRemove: true, enableTotalCount: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}

```

The generated graphql will include a `TodoItemSubTasksConnection` with a `totalCount` field.

```graphql {19}
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: CursorPaging = { first: 10 }

    filter: SubTaskFilter = {}

    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}

type TodoItemSubTasksConnection {
  pageInfo: PageInfo!
  edges: [SubTaskEdge!]!
  totalCount: Int!
}

```


## @FilterableCursorConnection

The `@FilterableCursorConnection` extends the `@CursorConnection` decorator exposing the ability to filter the `DTO` that defines the relation by relation properties.

:::warning
The `@FilterableCursorConnection` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`,
`sequelize`). If your relations are federated or you are using `mongoose` you cannot use the `@FilterableConnection`
decorator.
:::

### Example

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `TodoItems` by `subTasks`.

```ts title="todo-item/todo-item.dto.ts" {6}
import { FilterableField, IDField, FilterableCursorConnection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { SubTaskDTO } from '../sub-task/sub-task.dto'

@ObjectType('TodoItem')
@FilterableCursorConnection('subTasks', () => SubTaskDTO, { disableRemove: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  created!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date;
}

```
Notice the use of `@FilterableCursorConnection` instead of `@CursorConnection`, by using the `@FilterableCursorConnection` version `nestjs-query` will allow filtering on the `subTasks` relation.

The  module definition remains the same.

```ts title="todo-item/todo-item.module.ts"
import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
import { NestjsQueryTypeOrmModule } from '@nestjs-query/query-typeorm';
import { Module } from '@nestjs/common';
import { TodoItemDTO } from './todo-item.dto';
import { TodoItemEntity } from './todo-item.entity';

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }],
    }),
  ],
})
export class TodoItemModule {}
```

When querying for `TodoItems` you can now also filter on `subTasks` properties.

In this example we'll find all `todoItems` that have `subTasks` that are completed.
```graphql
{
  todoItems(filter: { subTasks: { completed: { is: true } } }) {
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    edges {
      node {
        id
        title
        description
        completed
        subTasks {
          edges {
            node {
              title
              description
              completed
            }
          }
        }
      }
      cursor
    }
  }
}
```

## Virtual Relations

You may run into a case where you have a `virtual` relation that does not exist in the database. `nestjs-query`
supports this through the [RelationQueryService](../concepts/services.md#relationqueryservice).

## Options

The following options can be passed to all relation/connection decorators, to customize
functionality.

* `relationName` - The name of the relation to use when looking up the relation from the `QueryService`
* `nullable` - Set to `true` if the relation is nullable.
* `complexity` - Set to specify relation complexity. For more info see [complexity docs](https://docs.nestjs.com/graphql/complexity)
* `disableRead` -  Set to `true` to disable read operations.
* `disableUpdate` -  Set to `true` to disable update operations.
* `disableRemove` -  Set to `true` to disable remove operations.
* `allowFiltering` - Set to `true` to allow filtering on the relation.
* `guards=[]` - An array of [guards](https://docs.nestjs.com/guards) to add to `update` and `remove` endpoints.
* `interceptors=[]` - An array of [interceptors](https://docs.nestjs.com/interceptors) to add to `update` and `remove` endpoints.
* `pipes=[]` - An array of [pipes](https://docs.nestjs.com/pipes) to add to `update` and `remove` endpoints.
* `filters=[]` - An array of [filters](https://docs.nestjs.com/exception-filters) to add to `update` and `remove` endpoints.

:::note
`guards`, `pipes`, `interceptors` and `filters` will not work by default with relation endpoints. See https://docs.nestjs.com/graphql/tooling#execute-enhancers-at-the-field-resolver-level
:::

### Custom Relation Name

Sometimes you may want to expose a relation that has a different name when persisted from the graphql property. To do this use the `relationName` property.

<Tabs
  defaultValue="relation"
  groupId="relation-type"
  values={[
    { label: 'Relation', value: 'relation', },
    { label: 'CursorConnection', value: 'cursor-connection', },
    { label: 'OffsetConnection', value: 'offset-connection', },
    { label: 'UnPagedRelation', value: 'unpaged-relation', },
  ]
}>
<TabItem value="relation">

```ts
// expose todoItem as todoItemRelation in graphql
@Relation('todoItemRelation', () => TodoItemDTO, { relationName: 'todoItem' })
```

</TabItem>
<TabItem value="cursor-connection">

```ts
// expose subTasks as subTaskConnection in graphql
@CursorConnection('subTaskConnection', () => SubTaskDTO, { relationName: 'subTasks' })
```

</TabItem>
<TabItem value="offset-connection">

```ts
// expose subTasks as subTaskConnection in graphql
@OffsetConnection('subTaskConnection', () => SubTaskDTO, { relationName: 'subTasks' })
```

</TabItem>
<TabItem value="unpaged-relation">

```ts
// expose subTasks as subTaskConnection in graphql
@UnPagedRelation('subTasks', () => SubTaskDTO, { relationName: 'subTasks' })
```

</TabItem>
</Tabs>

### Disable Reads

To disable the `read` `queries` you can set the `disableRead` option to `true`.

<Tabs
  defaultValue="relation"
  groupId="relation-type"
  values={[
    { label: 'Relation', value: 'relation', },
    { label: 'CursorConnection', value: 'cursor-connection', },
    { label: 'OffsetConnection', value: 'offset-connection', },
    { label: 'UnPagedRelation', value: 'unpaged-relation', },
  ]
}>
<TabItem value="relation">

```ts
// disable reading the todoItem relation
@Relation('todoItem', () => TodoItemDTO, { disableRead: true })
```

</TabItem>
<TabItem value="cursor-connection">

```ts
// disable reading the connection
@CursorConnection('subTasks', () => SubTaskDTO, { disableRead: true })
```

</TabItem>
<TabItem value="offset-connection">

```ts
// disable reading the relation
@OffsetConnection('subTaskConnection', () => SubTaskDTO, { disableRead: true })
```

</TabItem>
<TabItem value="unpaged-relation">

```ts
// disable reading the relation
@UnPagedRelation('subTaskConnection', () => SubTaskDTO, { disableRead: true })
```

</TabItem>
</Tabs>

### Disable Updates

To disable the `update` `mutations` you can set the `disableUpdate` option to `true`.

<Tabs
  defaultValue="relation"
  groupId="relation-type"
  values={[
    { label: 'Relation', value: 'relation', },
    { label: 'CursorConnection', value: 'cursor-connection', },
    { label: 'OffsetConnection', value: 'offset-connection', },
    { label: 'UnPagedRelation', value: 'unpaged-relation', },
  ]
}>
<TabItem value="relation">

```ts
// disable updates to the relation
@Relation('todoItem', () => TodoItemDTO, { disableUpdate: true })
```

</TabItem>
<TabItem value="cursor-connection">

```ts
// disable updating subTasks
@CursorConnection('subTasks', () => SubTaskDTO, { disableUpdate: true })
```

</TabItem>
<TabItem value="offset-connection">

```ts
// disable updating subTasks
@OffsetConnection('subTasks', () => SubTaskDTO, { disableUpdate: true })
```

</TabItem>
<TabItem value="unpaged-relation">

```ts
// disable updating subTasks
@UnPagedRelation('subTasks', () => SubTaskDTO, { disableUpdate: true })
```

</TabItem>
</Tabs>

### Disable Removes

To disable the `remove` `mutations` you can set the `disableRemove` option to `true`.

<Tabs
  defaultValue="relation"
  groupId="relation-type"
  values={[
    { label: 'Relation', value: 'relation', },
    { label: 'CursorConnection', value: 'cursor-connection', },
    { label: 'OffsetConnection', value: 'offset-connection', },
    { label: 'UnPagedRelation', value: 'unpaged-relation', },
  ]
}>
<TabItem value="relation">

```ts
// disable removing the relation
@Relation('todoItem', () => TodoItemDTO, { disableRemove: true })
```

</TabItem>
<TabItem value="cursor-connection">

```ts
// disable removing subTasks from the connection
@CursorConnection('subTasks', () => SubTaskDTO, { disableRemove: true })
```

</TabItem>
<TabItem value="offset-connection">

```ts
// disable removing subTasks from the connection
@OffsetConnection('subTasks', () => SubTaskDTO, { disableRemove: true })
```

</TabItem>
<TabItem value="unpaged-relation">

```ts
// disable removing subTasks from the relations
@UnPagedRelation('subTasks', () => SubTaskDTO, { disableRemove: true })
```

</TabItem>
</Tabs>

### Guards, Pipes and Filters

**NOTE** `guards`, `pipes`, `interceptors` and `filters` will not work by default with `read` endpoints. See https://github.com/nestjs/graphql/issues/295

In this example we'll just demonstrate using a `guard` but the same pattern applies for `pipes`, `filters` and
`interceptors`

To set up a [guard](https://docs.nestjs.com/guards) for endpoint you can use the `guards` option.

Assume we have the following auth guard that checks for a certain header and value.

```ts title="auth.guard.ts"
import {
  CanActivate,
  ExecutionContext,
  Injectable,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AUTH_HEADER_NAME } from './constants';
import { config } from './config';

@Injectable()
export class AuthGuard implements CanActivate {
  private logger = new Logger(AuthGuard.name);

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const ctx = GqlExecutionContext.create(context);
    const req = ctx.getContext().request;
    this.logger.log(`Req = ${req.headers}`);
    return req.headers[AUTH_HEADER_NAME] === config.auth.header;
  }
}
```

We can then add it to our relations


<Tabs
  defaultValue="relation"
  groupId="relation-type"
  values={[
    { label: 'Relation', value: 'relation', },
    { label: 'CursorConnection', value: 'cursor-connection', },
    { label: 'OffsetConnection', value: 'offset-connection', },
    { label: 'UnPagedRelation', value: 'unpaged-relation', },
  ]
}>
<TabItem value="relation">

```ts
// Add the AuthGuard using the guards option
@Relation('todoItem', () => TodoItemDTO, { guards: [AuthGuard] })
```

</TabItem>
<TabItem value="cursor-connection">

```ts
// Add the AuthGuard using the guards option
@CursorConnection('subTasks', () => SubTaskDTO, { guards: [AuthGuard] })
```

</TabItem>
<TabItem value="offset-connection">

```ts
// Add the AuthGuard using the guards option
@OffsetConnection('subTasks', () => SubTaskDTO, { guards: [AuthGuard] })
```

</TabItem>
<TabItem value="unpaged-relation">

```ts
// Add the AuthGuard using the guards option
@UnPagedRelation('subTasks', () => SubTaskDTO, { guards: [AuthGuard] })
```

</TabItem>
</Tabs>

Now any requests that go to the `update` or `remove` endpoints will require the guard.

### Relation Mixin

If you are using the [resolvers individually](./resolvers.mdx#individual-resolvers) you can use the following mixins to
add relations functionality.

#### Relatable

When using The `Relatable` mixin adds all relations functionality to a resolver.

In this example we expose on read endpoints for todo items with the relations defined on the `TodoItemDTO`.

```ts title="todo-item/todo-item.resolver.ts" {12-14}
import { ReadResolver, Relatable } from '@nestjs-query/query-graphql';
import { Resolver } from '@nestjs/graphql';
import { AuthGuard } from '../auth.guard';
import { SubTaskDTO } from '../sub-task/dto/sub-task.dto';
import { TodoItemDTO } from './todo-item.dto';
import { TodoItemService } from './todo-item.service';

const guards = [AuthGuard];

@Resolver(() => TodoItemDTO)
export class TodoItemResolver extends Relatable(TodoItemDTO)(ReadResolver(TodoItemDTO)) {
  constructor(readonly service: TodoItemService) {
    super(service);
  }
}
```
